/**
 * 
 */
package com.travelsky.app.persistence;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Version;

import org.apache.commons.lang.StringUtils;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.userdetails.UserDetails;

/**
 * 用户
 * @author zgch
 *
 */
@Entity(name = "SECURITY_USER")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@org.hibernate.annotations.Table(appliesTo = "SECURITY_USER",comment="用户")
public class User implements UserDetails,  Serializable {

	private static final long serialVersionUID = 8026813053768023527L;
	@Id
	@GeneratedValue
	@Column(name = "USER_ID", nullable = false, length = 18)
	private Long id;
	@Version
	@Column(name = "VERSION")
	private Long version;

	/**
	 *登录名 
	 */
	@Column(name = "USER_NAME", nullable = false, unique = true, length = 50)
	protected String name;
	/**
	 *用户真实姓名 
	 */
	@Column(name = "USER_REAL_NAME", nullable = false, length = 50)
	protected String userRealName;
	/**
	 *密码 
	 */
	@Column(name = "USER_PASSWORD", nullable = false, length = 50)
	protected String password;
	/**
	 *账户是否有效  true 无效  false 有效
	 */
	@Column(name = "DISABLED", nullable = false)
	protected boolean disabled;
	
	/**
	 *邮编 
	 */
	@Column(name = "POST", nullable = true, length = 15)
	protected String post;
	
	/**
	 * 传真号
	 */
	@Column(name = "FAX", nullable = true, length = 10)
	protected String fax;
	/**
	 * email
	 */
	@Column(name = "EMAIL", nullable = true, length = 20)
	protected String email;
	/**
	 * 联系地址
	 */
	@Column(name = "ADDRESS", nullable = true, length = 50)
	protected String address;
	/**
	 * 联系电话
	 */
	@Column(name = "PHONE", nullable = false, length = 20)
	protected String phone;
	/**
	 * 注册时间
	 */
	@Column(name = "REGIST_DATE", nullable = false)
	protected Date registDate;
	
	/**
	 * 备注
	 */
	@Column(name = "REMARK", nullable = true, length = 200)
	protected String remark;
	
	@ManyToMany(targetEntity = Role.class, fetch = FetchType.LAZY)
	@JoinTable(name = "SECURITY_USER_ROLE", joinColumns = @JoinColumn(name = "USER_ID"), inverseJoinColumns = @JoinColumn(name = "ROLE_ID"))
	@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
	private Set<Role> roles;

//	@Transient
//	private Map<String, List<Resource>> roleResources;

	/**
	 * The default constructor
	 */
	public User() {

	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#getAuthorities()
	 */
	public GrantedAuthority[] getAuthorities() {
		List<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>(roles.size());
		for (Role role : roles) {
			grantedAuthorities.add(new GrantedAuthorityImpl(role.getName()));
		}
		return grantedAuthorities.toArray(new GrantedAuthority[roles.size()]);
	}

	/**
	 * Returns the authorites string
	 * 
	 * eg. 
	 *    tangjj --- ROLE_ADMIN,ROLE_USER
	 *    tangdm --- ROLE_ADMIN
	 * 
	 * @return
	 */
	public String getAuthoritiesString() {
		List<String> authorities = new ArrayList<String>();
		for (GrantedAuthority authority : this.getAuthorities()) {
			authorities.add(authority.getAuthority());
		}
		return StringUtils.join(authorities.iterator(), ",");
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#getPassword()
	 */
	public String getPassword() {
		return password;
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#getUsername()
	 */
	public String getUsername() {
		return name;
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#isAccountNonExpired()
	 */
	public boolean isAccountNonExpired() {
		return true;
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#isAccountNonLocked()
	 */
	public boolean isAccountNonLocked() {
		return true;
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#isCredentialsNonExpired()
	 */
	public boolean isCredentialsNonExpired() {
		return true;
	}

	/* (non-Javadoc)
	 * @see org.springframework.security.userdetails.UserDetails#isEnabled()
	 */
	public boolean isEnabled() {
		return !disabled;
	}

	/**
	 * @return the id
	 */
	public Long getId() {
		return id;
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @return the disabled
	 */
	public boolean isDisabled() {
		return disabled;
	}

	/**
	 * @return the roles
	 */
	public Set<Role> getRoles() {
		return roles;
	}

	/**
	 * @return the roleResources
	 *//*
	public Map<String, List<Resource>> getRoleResources() {
		// init roleResources for the first time
		if (this.roleResources == null) {

			this.roleResources = new HashMap<String, List<Resource>>();

			for (Role role : this.roles) {
				String roleName = role.getName();
				Set<Resource> resources = role.getResources();
				for (Resource resource : resources) {
					String key = roleName + "_" + resource.getType();
					if (!this.roleResources.containsKey(key)) {
						this.roleResources.put(key, new ArrayList<Resource>());
					}
					this.roleResources.get(key).add(resource);
				}
			}

		}
		return this.roleResources;
	}
*/
	/**
	 * @param id the id to set
	 */
	public void setId(Long id) {
		this.id = id;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @param password the password to set
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/**
	 * @param disabled the disabled to set
	 */
	public void setDisabled(boolean disabled) {
		this.disabled = disabled;
	}

	/**
	 * @param roles the roles to set
	 */
	public void setRoles(Set<Role> roles) {
		this.roles = roles;
	}
	
	public String getPost() {
		return post;
	}

	public void setPost(String post) {
		this.post = post;
	}

	public String getFax() {
		return fax;
	}

	public void setFax(String fax) {
		this.fax = fax;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public Date getRegistDate() {
		return registDate;
	}

	public void setRegistDate(Date registDate) {
		this.registDate = registDate;
	}

	public String getRemark() {
		return remark;
	}

	public void setRemark(String remark) {
		this.remark = remark;
	}
	
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!(obj instanceof User))
			return false;
		User other = (User) obj;
		if (getName() == null) {
			if (other.getName() != null)
				return false;
		} else if (!getName().equals(other.getName()))
			return false;
		return true;
	}

	public String getUserRealName() {
		return userRealName;
	}

	public void setUserRealName(String userRealName) {
		this.userRealName = userRealName;
	}

}
